/**
 * @file ListType.c
 * @author 严一涵 (yyhhenry@foxmail.com)
 * @brief 双向链表的实现
 * @version 0.1
 * @date 2022-05-10
 * 
 * @copyright Copyright (c) 2022
 * 
 */
#include "./ListType.h"

void ListNode_free(ListNode *node, void (*free_ptr)(void *))
{
    free_ptr(node->ptr);
    free(node);
}

void *void_ListNode(ListNode *node)
{
    return node->ptr;
}

ListType *ListType_ListType(void (*free_ptr)(void *))
{
    ListType *list = (ListType *)malloc(sizeof(ListType));
    list->size = 0;
    list->head = NULL;
    list->tail = NULL;
    list->free_ptr = free_ptr;
    return list;
}

ListNode *ListType_insert(ListType *list, ListNode *node, void *ptr)
{
    ListNode *listNode = (ListNode *)malloc(sizeof(ListNode));
    listNode->ptr = ptr;
    listNode->prev = NULL;
    listNode->next = NULL;
    list->size++;
    if (node == NULL)
    {
        if (list->tail)
        {
            list->tail->next = listNode;
            listNode->prev = list->tail;
            list->tail = listNode;
        }
        else
        {
            list->head = listNode;
            list->tail = listNode;
        }
    }
    else if (node == list->head)
    {
        listNode->next = list->head;
        list->head->prev = listNode;
        list->head = listNode;
    }
    else
    {
        ListNode *pre = node->prev;
        pre->next = listNode;
        listNode->prev = pre;
        node->prev = listNode;
        listNode->next = node;
    }
    return listNode;
}

void ListType_remove(ListType *list, ListNode *node)
{
    if (node == NULL)
        return;
    list->size--;
    if (node == list->tail)
    {
        list->tail = node->prev;
        if (list->tail)
        {
            list->tail->next = NULL;
        }
        else
        {
            list->head = NULL;
        }
    }
    else if (node == list->head)
    {
        list->head = node->next;
        list->head->prev = NULL;
    }
    else
    {
        node->prev->next = node->next;
        node->next->prev = node->prev;
    }
    ListNode_free(node, list->free_ptr);
}

void ListType_free(ListType *list)
{
    while (list->size)
    {
        ListType_remove(list, list->head);
    }
    free(list);
}

void Ref_free(void *p)
{
    ;
}
